from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpRequest
from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from django import forms
from django.conf import settings
from asgiref.sync import sync_to_async
from pathlib import Path
from .models import User, Project, ProfilePhoto
from aiofiles import open as async_open
from django.contrib.auth.middleware import get_user
from os import makedirs
import os


def ensure_available(path: Path):
    if not path.parent.is_dir():
        makedirs(path.parent, exist_ok=True)
    return path


class LoginForm(forms.Form):
    username = forms.CharField(label="username", max_length=50)
    password = forms.CharField(label="password", max_length=50)


class RegisterForm(forms.Form):
    username = forms.CharField(label="username", max_length=50)
    password = forms.CharField(label="password", max_length=50)
    email = forms.CharField(label="email", max_length=100, required=False)


class PublishForm(forms.ModelForm):
    banner = forms.FileField(max_length=1024 * 1024 * 4)  # 4MB

    class Meta:
        model = Project
        fields = ["title", "description"]


def index_view(request: HttpRequest):
    return HttpResponse(render(request, "main/index.html", {}))


def new_index_view(request: HttpRequest):
    projects = Project.objects.all()

    return HttpResponse(render(request, "main/new-index.html", {"projects": projects}))


@login_required
def profile_view(request: HttpRequest):
    return HttpResponse(render(request, "main/profile.html", {}))


def project_detail_view(request: HttpRequest, id: int):
    try:
        project = Project.objects.get(pk=id)
    except Project.DoesNotExist as err:
        return HttpResponse(err, status=400)
    return HttpResponse(render(request, "main/project-details.html", {"project": project}))


async def publish_content_view(request: HttpRequest):
    user = await sync_to_async(get_user)(request)
    avatar = await sync_to_async(user.get_avatar)()

    if user.is_anonymous:
        from django.contrib.auth.views import redirect_to_login
        return redirect_to_login(request.get_full_path())
    if request.method == "GET":
        return HttpResponse(render(request, "main/publish-content.html", {"user": user, "avatar": avatar}))
    if request.method != "POST":
        return HttpResponse(f"{request.method} is not allowed", 400)  # unknown reason

    form = PublishForm(request.POST, request.FILES)
    if not form.is_valid():
        return HttpResponse(str(form.errors), status=400)

    title = form.cleaned_data["title"]
    description = form.cleaned_data["description"]
    banner = form.cleaned_data["banner"]
    ext: str = banner.content_type.split("/")[-1]  # from "image/png" to "png"
    if ext.lower() not in "webp png gif jpg jpeg bmp":
        return HttpResponse(f"file type {banner.content_type} not supportable", status=400)
    if banner.size > 1024 * 1024 * 4:
        return HttpResponse("file size must be less than 4MB", status=400)

    project = await sync_to_async(Project.objects.create)(title=title, description=description, creator=user)
    key = project.pk
    path = Path(settings.STATIC_ROOT) / "main" / "banners" / f"{key}.{ext}"
    async with async_open(ensure_available(path), "wb") as f:
        for chunk in banner.chunks():
            await f.write(chunk)

    project.metadata = {"banner": {
        "url": f"{request.scheme}://{request.get_host()}/{path.as_posix().lstrip('/')}",
        "filename": banner.name,
        "media_type": banner.content_type,
        "size": banner.size,
        "project": key
    }}
    await sync_to_async(project.save)()

    return redirect(f"/project/{project.pk}")


def login_view(request: HttpRequest):
    if request.method == "GET":
        return HttpResponse(render(request, "main/auth_views/login.html", {}))
    if request.method != "POST":
        return HttpResponse(f"{request.method} is not allowed", 400)  # unknown reason

    form = LoginForm(request.POST)
    if not form.is_valid():
        return HttpResponse(str(form.errors), status=400)

    username = form.cleaned_data["username"]
    password = form.cleaned_data["password"]

    user: User = authenticate(username=username, password=password)
    if user is not None:
        login(request, user)
        return redirect("/")
    else:
        return HttpResponse(render(request, "main/auth_views/login.html", {"message": "用户名或密码错误，请重试"}))


def register_view(request: HttpRequest):
    if request.method == "GET":
        return HttpResponse(render(request, "main/auth_views/register.html", {}))
    if request.method != "POST":
        return HttpResponse(f"{request.method} is not allowed", 400)  # unknown reason

    form = RegisterForm(request.POST)
    if not form.is_valid():
        return HttpResponse(str(form.errors), status=400)

    username = form.cleaned_data["username"]
    password = form.cleaned_data["password"]
    email = form.cleaned_data["email"]

    if User.objects.filter(username=username):
        message = "该用户名已存在，请直接登录"
        return redirect(f"/login?{message=!s}")
    if email and User.objects.filter(email=email):
        return HttpResponse(render(request, "main/auth_views/register.html", {"message": "该邮箱已被注册"}))

    login(request, User.objects.create_user(username, email, password))
    return redirect("/")


def edit_profile_view(request: HttpRequest):
    return HttpResponse(render(request, "main/edit-profile.html", {}))


def update_profile_photo(request: HttpRequest):
    if request.method == "GET":
        return HttpResponse(render(request, "main/profile.html", {}))

    if request.method != "POST":
        return HttpResponse(f"{request.method} is not allowed", status=400)  # unknown reason

    pic = request.FILES.get("pic")
    print(f"pic: {str(pic)}")

    username = request.user.username
    print(f"username: {username}")

    # ProfilePhoto.objects.create(username=username, pic=pic)

    user = ProfilePhoto.objects.filter(username=username)

    if user.exists():
        print(f"user {username} exists in database")
        profile_photo = ProfilePhoto.objects.get(username=username)

        # 删除static/media/pic中的图片
        original_path = profile_photo.pic.path
        if os.path.isfile(original_path):
            os.remove(original_path)

        # 修改数据库中的pic字段
        profile_photo.pic = pic
        profile_photo.save()
    else:
        print(f"user {username} does not exist in database")
        ProfilePhoto.objects.create(username=username, pic=pic)

    return HttpResponse(render(request, "main/profile.html", {}))
